/**
 * mksparse - make sparse file
 *
 * This program creates a sparse file with a hole at the specified position and size.
 * The file is created with the specified prefix and suffix.
 *
 * Usage:
 *   mksparse [--prefix 'PREFIX LINE\n'] [--suffix '\nSUFFIX CONTENT'] <file> <hole_pos> <hole_size>
 *
 * Example:
 *   mksparse sparse.img 1024 1024
 *   mksparse --prefix 'PREFIX LINE\n' --suffix '\nSUFFIX CONTENT' sparse.img 1024 1024
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <getopt.h>

#define DEFAULT_PREFIX ""
#define DEFAULT_SUFFIX ""

static void usage(const char *prog)
{
    fprintf(stderr, "Usage: %s [--prefix 'PREFIX LINE\\n'] [--suffix '\\nSUFFIX CONTENT'] <file> <hole_pos> <hole_size>\n", prog);
    exit(1);
}

int main(int argc, char *argv[])
{
    const char *prefix = DEFAULT_PREFIX;
    const char *suffix = DEFAULT_SUFFIX;
    const char *filename;
    off_t hole_pos;
    off_t hole_size;
    int fd;
    int opt;
    struct option longopts[] = {
        {"prefix", optional_argument, NULL, 'p'},
        {"suffix", optional_argument, NULL, 's'},
        {NULL, 0, NULL, 0}
    };

    /* Parse command line arguments */
    while ((opt = getopt_long(argc, argv, "p:s:", longopts, NULL)) != -1) {
        switch (opt) {
        case 'p':
            if (optarg) {
                prefix = optarg;
            } else if (optind < argc && argv[optind][0] != '-') {
                prefix = argv[optind++];
            }
            break;
        case 's':
            if (optarg) {
                suffix = optarg;
            } else if (optind < argc && argv[optind][0] != '-') {
                suffix = argv[optind++];
            }
            break;
        default:
            usage(argv[0]);
        }
    }

    if (optind + 3 != argc)
        usage(argv[0]);

    filename = argv[optind];
    hole_pos = atoll(argv[optind + 1]);
    hole_size = atoll(argv[optind + 2]);

    /* Open file for writing */
    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fd < 0) {
        fprintf(stderr, "Failed to open %s: %s\n", filename, strerror(errno));
        return 1;
    }

    /* Write prefix content */
    if (strlen(prefix) && write(fd, prefix, strlen(prefix)) < 0) {
        fprintf(stderr, "Failed to write prefix: %s\n", strerror(errno));
        close(fd);
        return 1;
    }

    /* Create hole */
    if (lseek(fd, hole_pos, SEEK_SET) < 0) {
        fprintf(stderr, "Failed to seek to hole position: %s\n", strerror(errno));
        close(fd);
        return 1;
    }

    if (lseek(fd, hole_size, SEEK_CUR) < 0) {
        fprintf(stderr, "Failed to create hole: %s\n", strerror(errno));
        close(fd);
        return 1;
    }

    /* Write suffix content */
    if (strlen(suffix) && write(fd, suffix, strlen(suffix)) < 0) {
        fprintf(stderr, "Failed to write suffix: %s\n", strerror(errno));
        close(fd);
        return 1;
    }

    close(fd);
    return 0;
}

